"""
教学质量评估主服务
"""
import asyncio
import numpy as np
from datetime import datetime, timedelta
from typing import List, Dict, Optional, Tuple, Any
from uuid import uuid4
from collections import defaultdict

from services.teaching_quality_assessment.teaching_quality_service import (
    TeacherBehaviorAnalyzer, TeacherBehaviorData, TeachingQualityReport,
    TeachingBehavior, TeachingStyle, FatigueLevel, InteractionQuality
)
from services.teaching_quality_assessment.teaching_quality_service import InteractionAnalyzer, InteractionData
from services.teaching_quality_assessment.teaching_style_analyzer import TeachingStyleAnalyzer, TeachingStyleAnalysis


class TeachingQualityService:
    """教学质量评估服务"""
    
    def __init__(self):
        self.behavior_analyzer = TeacherBehaviorAnalyzer()
        self.interaction_analyzer = InteractionAnalyzer()
        self.style_analyzer = TeachingStyleAnalyzer()
        
        # 数据存储
        self.teacher_behavior_storage = defaultdict(list)
        self.interaction_storage = defaultdict(list)
        self.style_analysis_storage = {}
        self.quality_reports_storage = {}
    
    async def analyze_teacher_behavior(self, image: np.ndarray, teacher_detection: Dict[str, Any],
                                     audio_features: Optional[Dict[str, Any]] = None) -> TeacherBehaviorData:
        """分析教师行为"""
        teacher_id = teacher_detection['teacher_id']
        bbox = teacher_detection['bbox']
        
        # 执行行为分析
        behavior_data = await self.behavior_analyzer.analyze_teacher_behavior(
            image, bbox, teacher_id, audio_features
        )
        
        # 存储数据
        self.teacher_behavior_storage[teacher_id].append(behavior_data)
        
        return behavior_data
    
    async def analyze_interaction(self, teacher_id: str, student_attention_data: List[Any],
                                audio_features: Optional[Dict[str, Any]] = None) -> InteractionData:
        """分析师生互动"""
        # 获取最新的教师行为数据
        teacher_behaviors = self.teacher_behavior_storage.get(teacher_id, [])
        if not teacher_behaviors:
            raise ValueError(f"教师 {teacher_id} 没有行为数据")
        
        latest_behavior = teacher_behaviors[-1]
        
        # 执行互动分析
        interaction_data = await self.interaction_analyzer.analyze_interaction(
            teacher_id, latest_behavior, student_attention_data, audio_features
        )
        
        # 存储数据
        self.interaction_storage[teacher_id].append(interaction_data)
        
        return interaction_data
    
    def analyze_teaching_style(self, teacher_id: str) -> TeachingStyleAnalysis:
        """分析教学风格"""
        behavior_history = self.teacher_behavior_storage.get(teacher_id, [])
        interaction_history = self.interaction_storage.get(teacher_id, [])
        
        if not behavior_history:
            raise ValueError(f"教师 {teacher_id} 没有足够的行为数据进行风格分析")
        
        # 执行风格分析
        style_analysis = self.style_analyzer.analyze_teaching_style(
            teacher_id, behavior_history, interaction_history
        )
        
        # 存储分析结果
        self.style_analysis_storage[style_analysis.analysis_id] = style_analysis
        
        return style_analysis
    
    def generate_quality_report(self, teacher_id: str, classroom_id: str,
                              time_range: Optional[Tuple[datetime, datetime]] = None) -> TeachingQualityReport:
        """生成教学质量报告"""
        report_id = str(uuid4())
        
        # 获取相关数据
        behavior_history = self.teacher_behavior_storage.get(teacher_id, [])
        interaction_history = self.interaction_storage.get(teacher_id, [])
        
        if not behavior_history:
            raise ValueError(f"教师 {teacher_id} 没有足够的数据生成报告")
        
        # 筛选时间范围内的数据
        if time_range:
            start_time, end_time = time_range
            behavior_history = [
                data for data in behavior_history
                if start_time <= data.timestamp <= end_time
            ]
            interaction_history = [
                data for data in interaction_history
                if start_time <= data.timestamp <= end_time
            ]
        
        # 确定分析周期
        if behavior_history:
            timestamps = [data.timestamp for data in behavior_history]
            analysis_period = (min(timestamps), max(timestamps))
        else:
            analysis_period = time_range or (datetime.now() - timedelta(hours=1), datetime.now())
        
        # 行为分析
        behavior_analysis = self._analyze_behavior_patterns(behavior_history)
        
        # 互动分析
        interaction_analysis = self._analyze_interaction_patterns(interaction_history)
        
        # 风格分析
        style_analysis = self.style_analyzer.analyze_teaching_style(
            teacher_id, behavior_history, interaction_history
        )
        
        # 疲劳度分析
        fatigue_analysis = self._analyze_fatigue_patterns(behavior_history)
        
        # 计算综合评分
        overall_score = self._calculate_overall_score(
            behavior_analysis, interaction_analysis, style_analysis, fatigue_analysis
        )
        
        # 生成改进建议
        improvement_suggestions = self._generate_improvement_suggestions(
            behavior_analysis, interaction_analysis, style_analysis, fatigue_analysis
        )
        
        report = TeachingQualityReport(
            report_id=report_id,
            teacher_id=teacher_id,
            classroom_id=classroom_id,
            analysis_period=analysis_period,
            overall_score=overall_score,
            behavior_analysis=behavior_analysis,
            interaction_analysis=interaction_analysis,
            style_analysis=style_analysis,
            fatigue_analysis=fatigue_analysis,
            improvement_suggestions=improvement_suggestions,
            generated_at=datetime.now()
        )
        
        # 存储报告
        self.quality_reports_storage[report_id] = report
        
        return report
    
    def _analyze_behavior_patterns(self, behavior_history: List[TeacherBehaviorData]) -> Dict[str, Any]:
        """分析行为模式"""
        if not behavior_history:
            return {}
        
        # 行为分布统计
        behavior_counts = defaultdict(int)
        total_behaviors = len(behavior_history)
        
        for behavior_data in behavior_history:
            behavior_counts[behavior_data.behavior.value] += 1
        
        behavior_distribution = {
            behavior: count / total_behaviors
            for behavior, count in behavior_counts.items()
        }
        
        # 手势分析
        gesture_intensities = [data.gesture_data.get('intensity', 0) for data in behavior_history]
        avg_gesture_intensity = np.mean(gesture_intensities)
        
        # 语音分析
        voice_qualities = [data.voice_features.get('voice_quality', 0) for data in behavior_history if data.voice_features]
        avg_voice_quality = np.mean(voice_qualities) if voice_qualities else 0
        
        # 移动模式分析
        movement_frequencies = [data.movement_data.get('movement_frequency', 0) for data in behavior_history]
        avg_movement_frequency = np.mean(movement_frequencies)
        
        return {
            'behavior_distribution': behavior_distribution,
            'avg_gesture_intensity': avg_gesture_intensity,
            'avg_voice_quality': avg_voice_quality,
            'avg_movement_frequency': avg_movement_frequency,
            'total_observations': total_behaviors,
            'dominant_behavior': max(behavior_counts.items(), key=lambda x: x[1])[0] if behavior_counts else None
        }
    
    def _analyze_interaction_patterns(self, interaction_history: List[InteractionData]) -> Dict[str, Any]:
        """分析互动模式"""
        if not interaction_history:
            return {
                'interaction_frequency': 0,
                'avg_engagement': 0,
                'avg_effectiveness': 0,
                'quality_distribution': {}
            }
        
        # 互动频率
        interaction_frequency = len(interaction_history)
        
        # 平均参与度和有效性
        avg_engagement = np.mean([data.engagement_score for data in interaction_history])
        avg_effectiveness = np.mean([data.effectiveness_score for data in interaction_history])
        
        # 质量分布
        quality_counts = defaultdict(int)
        for data in interaction_history:
            quality_counts[data.interaction_quality.value] += 1
        
        quality_distribution = {
            quality: count / len(interaction_history)
            for quality, count in quality_counts.items()
        }
        
        # 问答统计
        total_questions = sum(data.teacher_question_count for data in interaction_history)
        total_responses = sum(data.student_response_count for data in interaction_history)
        
        return {
            'interaction_frequency': interaction_frequency,
            'avg_engagement': avg_engagement,
            'avg_effectiveness': avg_effectiveness,
            'quality_distribution': quality_distribution,
            'total_questions': total_questions,
            'total_responses': total_responses,
            'avg_questions_per_interaction': total_questions / interaction_frequency if interaction_frequency > 0 else 0,
            'avg_responses_per_interaction': total_responses / interaction_frequency if interaction_frequency > 0 else 0
        }
    
    def _analyze_fatigue_patterns(self, behavior_history: List[TeacherBehaviorData]) -> Dict[str, Any]:
        """分析疲劳模式"""
        if not behavior_history:
            return {}
        
        # 疲劳度分布
        fatigue_counts = defaultdict(int)
        for data in behavior_history:
            fatigue_counts[data.fatigue_level.value] += 1
        
        fatigue_distribution = {
            level: count / len(behavior_history)
            for level, count in fatigue_counts.items()
        }
        
        # 疲劳度趋势
        fatigue_scores = []
        fatigue_mapping = {
            FatigueLevel.VERY_LOW: 1,
            FatigueLevel.LOW: 2,
            FatigueLevel.MEDIUM: 3,
            FatigueLevel.HIGH: 4,
            FatigueLevel.VERY_HIGH: 5
        }
        
        for data in behavior_history:
            fatigue_scores.append(fatigue_mapping[data.fatigue_level])
        
        avg_fatigue_score = np.mean(fatigue_scores)
        
        # 疲劳度趋势（简单线性回归）
        if len(fatigue_scores) > 1:
            x = np.arange(len(fatigue_scores))
            slope = np.polyfit(x, fatigue_scores, 1)[0]
            if slope > 0.1:
                fatigue_trend = "increasing"
            elif slope < -0.1:
                fatigue_trend = "decreasing"
            else:
                fatigue_trend = "stable"
        else:
            fatigue_trend = "stable"
        
        return {
            'fatigue_distribution': fatigue_distribution,
            'avg_fatigue_score': avg_fatigue_score,
            'fatigue_trend': fatigue_trend,
            'high_fatigue_ratio': fatigue_distribution.get('high', 0) + fatigue_distribution.get('very_high', 0)
        }
    
    def _calculate_overall_score(self, behavior_analysis: Dict[str, Any],
                               interaction_analysis: Dict[str, Any],
                               style_analysis: TeachingStyleAnalysis,
                               fatigue_analysis: Dict[str, Any]) -> float:
        """计算综合评分"""
        score = 0
        
        # 行为表现分数 (30%)
        behavior_score = 0
        if behavior_analysis:
            gesture_score = behavior_analysis.get('avg_gesture_intensity', 0) * 100
            voice_score = behavior_analysis.get('avg_voice_quality', 0) * 100
            movement_score = behavior_analysis.get('avg_movement_frequency', 0) * 100
            behavior_score = (gesture_score + voice_score + movement_score) / 3
        
        score += behavior_score * 0.3
        
        # 互动表现分数 (40%)
        interaction_score = 0
        if interaction_analysis:
            engagement_score = interaction_analysis.get('avg_engagement', 0)
            effectiveness_score = interaction_analysis.get('avg_effectiveness', 0)
            interaction_score = (engagement_score + effectiveness_score) / 2
        
        score += interaction_score * 0.4
        
        # 教学风格适应性分数 (20%)
        style_score = style_analysis.style_confidence * 100 if style_analysis else 50
        score += style_score * 0.2
        
        # 疲劳度影响 (10%)
        fatigue_penalty = 0
        if fatigue_analysis:
            high_fatigue_ratio = fatigue_analysis.get('high_fatigue_ratio', 0)
            fatigue_penalty = high_fatigue_ratio * 30  # 高疲劳度扣分
        
        fatigue_score = max(0, 100 - fatigue_penalty)
        score += fatigue_score * 0.1
        
        return min(100, max(0, score))
    
    def _generate_improvement_suggestions(self, behavior_analysis: Dict[str, Any],
                                        interaction_analysis: Dict[str, Any],
                                        style_analysis: TeachingStyleAnalysis,
                                        fatigue_analysis: Dict[str, Any]) -> List[str]:
        """生成改进建议"""
        suggestions = []
        
        # 基于行为分析的建议
        if behavior_analysis:
            if behavior_analysis.get('avg_gesture_intensity', 0) < 0.5:
                suggestions.append("建议增加手势表达，提高教学的生动性")
            
            if behavior_analysis.get('avg_voice_quality', 0) < 0.6:
                suggestions.append("注意语音质量，保持清晰的发音和适当的音量")
            
            if behavior_analysis.get('avg_movement_frequency', 0) < 0.3:
                suggestions.append("适当增加课堂走动，与学生保持更好的互动距离")
        
        # 基于互动分析的建议
        if interaction_analysis:
            if interaction_analysis.get('avg_engagement', 0) < 60:
                suggestions.append("增加互动环节，提高学生参与度")
            
            if interaction_analysis.get('avg_effectiveness', 0) < 70:
                suggestions.append("优化互动方式，提升教学效果")
            
            if interaction_analysis.get('avg_questions_per_interaction', 0) < 1:
                suggestions.append("增加课堂提问频率，引导学生思考")
        
        # 基于风格分析的建议
        if style_analysis and style_analysis.improvement_areas:
            suggestions.extend(style_analysis.recommendations[:2])  # 取前2个建议
        
        # 基于疲劳分析的建议
        if fatigue_analysis:
            if fatigue_analysis.get('high_fatigue_ratio', 0) > 0.3:
                suggestions.append("注意休息，避免过度疲劳影响教学质量")
            
            if fatigue_analysis.get('fatigue_trend') == 'increasing':
                suggestions.append("建议调整教学节奏，适当安排休息时间")
        
        return suggestions
    
    def get_teacher_statistics(self, teacher_id: str,
                             time_range: Optional[Tuple[datetime, datetime]] = None) -> Dict[str, Any]:
        """获取教师统计信息"""
        behavior_history = self.teacher_behavior_storage.get(teacher_id, [])
        interaction_history = self.interaction_storage.get(teacher_id, [])
        
        # 筛选时间范围
        if time_range:
            start_time, end_time = time_range
            behavior_history = [
                data for data in behavior_history
                if start_time <= data.timestamp <= end_time
            ]
            interaction_history = [
                data for data in interaction_history
                if start_time <= data.timestamp <= end_time
            ]
        
        if not behavior_history:
            return {'error': f'教师 {teacher_id} 在指定时间范围内没有数据'}
        
        # 基础统计
        total_observations = len(behavior_history)
        total_interactions = len(interaction_history)
        
        # 行为统计
        behavior_counts = defaultdict(int)
        for data in behavior_history:
            behavior_counts[data.behavior.value] += 1
        
        most_common_behavior = max(behavior_counts.items(), key=lambda x: x[1])[0] if behavior_counts else None
        
        # 疲劳度统计
        fatigue_counts = defaultdict(int)
        for data in behavior_history:
            fatigue_counts[data.fatigue_level.value] += 1
        
        avg_fatigue = np.mean([
            {'very_low': 1, 'low': 2, 'medium': 3, 'high': 4, 'very_high': 5}[data.fatigue_level.value]
            for data in behavior_history
        ])
        
        # 互动统计
        avg_engagement = np.mean([data.engagement_score for data in interaction_history]) if interaction_history else 0
        avg_effectiveness = np.mean([data.effectiveness_score for data in interaction_history]) if interaction_history else 0
        
        return {
            'teacher_id': teacher_id,
            'time_range': time_range,
            'total_observations': total_observations,
            'total_interactions': total_interactions,
            'behavior_distribution': dict(behavior_counts),
            'most_common_behavior': most_common_behavior,
            'fatigue_distribution': dict(fatigue_counts),
            'avg_fatigue_level': avg_fatigue,
            'avg_engagement_score': avg_engagement,
            'avg_effectiveness_score': avg_effectiveness
        }